package menu

import (
	"context"
	"net/http"

	"go-zero-admin/apps/system/cmd/api/internal/svc"
	"go-zero-admin/apps/system/cmd/api/internal/types"
	"go-zero-admin/apps/system/cmd/rpc/syspb"
	"go-zero-admin/pkg/constant"
	"go-zero-admin/pkg/ctxdata"

	"github.com/jinzhu/copier"
	"github.com/zeromicro/go-zero/core/logx"
)

type ListMenuLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
	r      *http.Request
}

func NewListMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext, r *http.Request) *ListMenuLogic {
	return &ListMenuLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
		r:      r,
	}
}

func (l *ListMenuLogic) ListMenu(req *types.ListMenuReq) (resp *types.ListMenuResp, err error) {
	listRpc, err := l.svcCtx.MenuRpc.GetMenuList(l.ctx, &syspb.GetMenuListReq{
		Title:           req.Title,
		Component:       req.Component,
		IsDataScope:     true,
		DataScopeUserId: ctxdata.GetUidFromCtx(l.ctx),
	})
	if err != nil {
		return nil, err
	}
	if len(listRpc.GetList()) == 0 {
		return &types.ListMenuResp{Rules: []*types.SysMenuTree{}}, nil
	}

	// 处理数据
	var list []*types.SysMenu
	for _, menuRpc := range listRpc.GetList() {
		var menu types.SysMenu
		_ = copier.Copy(&menu, menuRpc)
		list = append(list, &menu)
	}

	// 处理规则
	var rules []*types.SysMenuTree
	if req.Title != "" || req.Component != "" {
		for _, menu := range list {
			rules = append(rules, &types.SysMenuTree{
				SysMenu: menu,
			})
		}
	} else {
		// 菜单必须是一个顶级pid=0开始，所以构建tree无需动态判断pid
		// 如用户勾选无顶级pid=0，则不显示数据tree
		rules = l.getMenuListTree(constant.MenuFirstPid, list)
	}

	return &types.ListMenuResp{Rules: rules}, nil
}

// 获取树状结构
func (l *ListMenuLogic) getMenuListTree(pid int64, list []*types.SysMenu) []*types.SysMenuTree {
	tree := make([]*types.SysMenuTree, 0)
	for _, menu := range list {
		if menu.Pid != pid {
			continue
		}

		t := &types.SysMenuTree{
			SysMenu:  menu,
			Children: l.getMenuListTree(menu.Id, list),
		}

		tree = append(tree, t)
	}
	return tree
}
